package com.ld.admin.service.system;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.RegExUtils;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import com.ld.admin.config.SystemStaticParams;
import com.ld.admin.model.system.SysMenuModel;
import com.ld.admin.model.system.SysRoleModel;
import com.ld.admin.model.system.SysRolePermissionModel;
import com.ld.admin.plugin.cache.MappingUrlCacheUtil;
import com.ld.admin.plugin.cache.MenuCacheUtil;
import com.ld.admin.plugin.cache.PermCacheUtil;
import com.ld.admin.util.SystemSetConfig;
import com.ld.common.service.ProjectBasicService;
import com.ld.common.util.SharedVarsUtil;
import com.ld.shieldsb.common.composition.util.web.Global;
import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.io.ResourceUtils;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.reflect.ClassUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.web.StaticParams;
import com.ld.shieldsb.common.web.util.Web;
import com.ld.shieldsb.dao.TransactionManager;
import com.ld.shieldsb.dao.model.PageNavigationBean;
import com.ld.shieldsb.dao.model.QueryModel;

/**
 * 
 * 菜单服务类，@Service注解用于自动注入
 * 
 * @ClassName SysTimedtaskService
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2019年01月04日 14:29:47
 *
 */
@Service
public class SysMenuService extends ProjectBasicService {
    protected static final int LIST_MAX_NUM = 10;

    // 用于子类覆盖，扩展doSearch方法中QueryModel的处理（标准queryModel处理完，查询进行前的处理）
    @Override
    protected QueryModel extendDealQuery(QueryModel queryModel) {
//        queryModel.setCondition("     jobName='test' and (select * from (select(sleep(5)))Desn) and status!=? "); //测试sql注入
        return super.extendDealQuery(queryModel);
    }

    // 用于子类覆盖，扩展doSearch方法中PageNavigationBean的处理（查询完成后进行）
    @Override
    protected <T> PageNavigationBean<T> extendDealPageNavigationBean(PageNavigationBean<T> pageNavigationBean) {
        return super.extendDealPageNavigationBean(pageNavigationBean);
    }

    // 删除方法子类扩展（删除完成后进行）
    @Override
    protected <T> boolean extendRemove(Boolean flag, Class<T> classOfT, String key, Object value, Integer status, Long userId) {
        if (flag) {
            MenuCacheUtil.reloadCache(); // 刷新菜单
            PermCacheUtil.reloadCache(); // 刷新权限
        }
        return flag;
    }

    // AddOrUpdate扩展（AddOrUpdate方法完成后进行）
    @Override
    protected <T> boolean extendAddOrUpdate(Boolean flag, T modelBean, boolean update, String key, Long userId) {
        if (flag) {
            MenuCacheUtil.reloadCache(); // 刷新菜单
            PermCacheUtil.reloadCache(); // 刷新权限
        }
        return flag;
    }

    // AddOrUpdate扩展（AddOrUpdate方法完成后进行）
    @Override
    protected <T> boolean extendAddOrUpdate(Boolean flag, List<T> modelBean, boolean update, String key, Long userId) {
        if (flag) {
            MenuCacheUtil.reloadCache(); // 刷新菜单
            PermCacheUtil.reloadCache(); // 刷新权限
        }
        return flag;
    }

    @Override
    public <T> Result addOrUpdate(T modelBean, boolean update) {
        SysMenuModel menuModel = (SysMenuModel) modelBean;
        String href = menuModel.getHref();
        if (href != null) {
            href = com.ld.shieldsb.common.core.util.StringUtils.stripBlank(href);
            if (href.equals("${ctxPathA}") || href.equals("${ctxPath}") || href.equals("${ctxPathF}")) {// 添加
                return Web.Response.error("href不能只填写内置变量，请修改为正确的值！");
            }
        }
        return super.addOrUpdate(modelBean, update);
    }

    /**
     * 添加修改系统权限（与菜单分开）
     * 
     * @Title addOrUpdatePermisson
     * @author 吕凯
     * @date 2019年3月25日 上午11:05:07
     * @param modelBean
     * @param update
     * @return Result
     */
    public <T> Result addOrUpdatePermisson(T modelBean, boolean update) {
        SysMenuModel menuModel = (SysMenuModel) modelBean;
        String href = menuModel.getHref();
        if (href != null) {
            href = com.ld.shieldsb.common.core.util.StringUtils.stripBlank(href);
            if (href.equals("${ctxPathA}") || href.equals("${ctxPath}") || href.equals("${ctxPathF}")) {// 添加
                return Web.Response.error("href不能只填写内置变量，请修改为正确的值！");
            }
        }
        if (!update) {// 添加
            menuModel.setType(SystemStaticParams.MENU_TYPE_BUTTON); // 按钮
        }
        return super.addOrUpdate(modelBean, update);
    }

    /**
     * 获取菜单数据，数据格式为json格式
     * 
     * @Title getMenusData
     * @author 吕凯
     * @date 2019年1月14日 上午11:42:32
     * @param request
     * @return Result
     */
    public Result getMenusData(HttpServletRequest request) {
        Result result = getData(request, 1, null); // 菜单
        return result;
    }

    /**
     * 
     * 获取权限数据，数据格式为json格式
     * 
     * @Title getPermsData
     * @author 吕凯
     * @date 2019年3月27日 下午2:06:27
     * @param request
     * @return Result
     */
    public Result getPermsData(HttpServletRequest request) {
        Result result = getData(request, 2, null); // 权限，权限包含菜单
        return result;
    }

    /**
     * 
     * 获取拥有权限的角色
     * 
     * @Title getHasPermsRoles
     * @author 吕凯
     * @date 2019年9月19日 下午3:41:15
     * @param request
     *            用来赋值
     * @param permId
     *            权限id
     * @return List<SysRoleModel>
     */
    public List<SysRoleModel> getHasPermsRoles(HttpServletRequest request, Long permId) {
        List<SysRoleModel> list = null;
        if (permId != null && permId > 0) {
            QueryModel queryModel = super.getSearchQueryModel(request);
            queryModel.setOrder("createTime", true);
            queryModel.addM2MIdLinkByExists(SysRoleModel.class, SysRoleModel::getPermissions, permId); // 多对多的主键关联，即查询permId下的角色
            list = getList(SysRoleModel.class, queryModel);
        }
        request.setAttribute("rolePerms", list);
        return list;
    }

    /**
     * 根据类型获取数据
     * 
     * @Title getData
     * @author 吕凯
     * @date 2019年3月27日 下午2:06:44
     * @param request
     * @param type
     * @return Result
     */
    private Result getData(HttpServletRequest request, int type, Integer isShow) {
        QueryModel queryModel = getSearchQueryModel(request);
        String name = getString("like_name");
        Set<Integer> types = new HashSet<>();
        types.add(1);
        if (type == 2) { // 获取权限
            types.add(2);
        }
        if (isShow != null) {
            queryModel.addEq("is_show", StaticParams.SHOW_YES); // 显示的
        }
        queryModel.addInSet("type", types); // 菜单
        queryModel.setOrder("sort", false); // 按sort排序
        List<SysMenuModel> list = getAll(SysMenuModel.class, queryModel);
        Result result = new Result();
        List<Map<String, Object>> listMap = new ArrayList<>();
        list.stream().forEach(model -> {
            Map<String, Object> dataMap = new LinkedHashMap<>();
            String permName = model.getName();
            if (!StringUtils.isBlank(name) && permName.contains(name)) { // 搜索着重显示,未使用
//              String fontClsStr = "{'color':'black','font-weight':'bold'}";
//              Map<String, String> fontClsMap = (Map<String, String>) JSONObject.parseObject(fontClsStr, Map.class);
//              dataMap.put("font", fontClsMap);
                permName = permName.replaceAll(name, "<font style='font-weight:bold;color:red;'>" + name + "</font>");
            }
            if (model.getIsShow() == 0) { // 隐藏的处理一下样式
                Map<String, String> fontClsMap = new HashMap<>();
                fontClsMap.put("color", "gray"); // 灰色
                String color = SystemSetConfig.getString(SystemSetConfig.MENU_HIDDEN_COLOR); // 颜色
                if (StringUtils.isNoneBlank(color)) {
                    fontClsMap.put("color", color); // 颜色
                }
                String fontStyle = SystemSetConfig.getString(SystemSetConfig.MENU_HIDDEN_FONTSTYLE); //
                if (StringUtils.isNoneBlank(fontStyle)) {
//                    fontClsMap.put("font-style", "italic"); // 斜体
                    fontClsMap.put("font-style", fontStyle); // 斜体
                }
                String textDecoration = SystemSetConfig.getString(SystemSetConfig.MENU_HIDDEN_TEXTDECORATION); //
                if (StringUtils.isNoneBlank(textDecoration)) {
                    fontClsMap.put("text-decoration", textDecoration); // 删除线
//                    fontClsMap.put("text-decoration", "line-through"); // 删除线
                }
                if (!fontClsMap.isEmpty()) {
                    dataMap.put("font", fontClsMap);
                }
            } else if (SystemStaticParams.MENU_TYPE_BUTTON == model.getType()) { // 按钮处理一下样式
                String color = SystemSetConfig.getString(SystemSetConfig.MENU_PERM_COLOR); // 颜色
                if (StringUtils.isNoneBlank(color)) {
                    Map<String, String> fontClsMap = new HashMap<>();
                    fontClsMap.put("color", color); // 颜色
//                    fontClsMap.put("color", "blue"); // 蓝色
                    dataMap.put("font", fontClsMap);
                }
                String skin = SystemSetConfig.getString(SystemSetConfig.MENU_PERM_SKIN); // 颜色
                if (StringUtils.isNoneBlank(skin)) {
                    dataMap.put("iconSkin", skin); // 样式前缀，自定义对应的样式，没有子级的样式是xxx_ico_docu,有自己的是xxx_ico_open,xxx_ico_close
                }
            }
            if (type == 2) { // 获取权限
                Integer permType = model.getPermType();
                if (permType != null) {
                    if (permType == 0) {
//                    dataMap.put("nocheck", true); // 不可选
                        permName += SystemSetConfig.getString(SystemSetConfig.MENU_PERM_NO_NAMESUFFIX);
                        String color = SystemSetConfig.getString(SystemSetConfig.MENU_PERM_NO_COLOR); // 颜色
                        if (StringUtils.isNoneBlank(color)) {
                            Map<String, String> fontClsMap = new HashMap<>();
                            fontClsMap.put("color", color); // 颜色
                            dataMap.put("font", fontClsMap);
                        }
                    } else if (permType == 2) {
//                    dataMap.put("nocheck", true); // 不可选
                        permName += SystemSetConfig.getString(SystemSetConfig.MENU_PERM_LOGIN_NAMESUFFIX);
                        String color = SystemSetConfig.getString(SystemSetConfig.MENU_PERM_LOGIN_COLOR);
                        if (StringUtils.isNoneBlank(color)) {
                            Map<String, String> fontClsMap = new HashMap<>();
                            fontClsMap.put("color", color); // 颜色
                            dataMap.put("font", fontClsMap);
                        }
                    }
                }
            }
            dataMap.put("name", permName);
            dataMap.put("permType", model.getPermType()); // 权限类型
            dataMap.put("id", model.getId() + ""); // long精度损失，转为字符型
            dataMap.put("pId", model.getParentId() + ""); // long精度损失，转为字符型
            dataMap.put("open", false); // 是否展开，用于有下级的情况
            String operation = model.getOperation() == null ? "" : model.getOperation();
            dataMap.put("canDelete", operation.contains("D")); // 是否可删除
            dataMap.put("canUpdate", operation.contains("U")); // 是否可删除
            listMap.add(dataMap);
        });
        result.setData(listMap);
        result.setSuccess(true);
        return result;
    }

    /**
     * 获取用户的权限
     * 
     * @Title getData
     * @author 吕凯
     * @date 2019年3月27日 下午2:06:44
     * @param request
     * @param type
     * @return Result
     */
    @SuppressWarnings("unchecked")
    public Result getRolePermData(HttpServletRequest request, long roleId) {
        Result result = getData(request, 2, StaticParams.SHOW_YES); // 权限，权限包含菜单,
        QueryModel queryModel = getSearchQueryModel(request);
        queryModel.addEq("roleId", roleId); // 菜单
        List<SysRolePermissionModel> rolePermlist = getAll(SysRolePermissionModel.class, queryModel); // 角色权限

        List<Map<String, Object>> permMapList = (List<Map<String, Object>>) result.getData();
        for (Map<String, Object> dataMap : permMapList) {
            String idString = (String) dataMap.get("id"); // id
            for (SysRolePermissionModel rolePerm : rolePermlist) {
                if ((rolePerm.getPermissionId() + "").equals(idString)) {
                    dataMap.put("checked", true); // 设置以及拥有的权限
                    break;
                }

            }
//            Integer permType = (Integer) dataMap.get("permType"); // id
//            String name = (String) dataMap.get("name"); // id
//            if (permType != null) {
//                if (permType == 0) {
//                } else if (permType == 2) {
//                }
//            }
        }
        result.setData(permMapList);
        return result;
    }

    /**
     * 保存用户权限
     * 
     * @Title saveRolePermData
     * @author 吕凯
     * @date 2019年3月28日 下午6:26:47
     * @param request
     * @param roleId
     * @return Result
     */
    public Result saveRolePerms(long roleId) {
        Result result = new Result();
        String[] permissionIds = null;
        String permissiondata = getString("permissiondata");
        if (roleId == 0) {
            result.setMessage("未选中角色！");
            return result;
        }
        if (!StringUtils.isBlank(permissiondata)) {
            try {
                TransactionManager.start();
                permissionIds = permissiondata.split(",");
                BaseDAO.delete(SysRolePermissionModel.class, "roleId", roleId);
                List<SysRolePermissionModel> models = new ArrayList<SysRolePermissionModel>();
                for (int i = 0; i < permissionIds.length; i++) {
                    SysRolePermissionModel model = new SysRolePermissionModel();
                    model.setPermissionId(ClassUtil.obj2long(permissionIds[i]));
                    model.setRoleId(roleId);
                    models.add(model);
                }
                result = super.addOrUpdate(models, false);
                if (result.getSuccess()) {
                    result.setMessage("修改角色权限成功！下次登录生效");
                } else {
                    result.setMessage("修改权限失败！" + result.getMessage());
                }
                TransactionManager.commit(); // 提交事务
            } catch (Exception e) {
                try {
                    TransactionManager.rollback();
                } catch (SQLException e1) {
                    log.error("", e1);
                } // 回滚
                log.error("", e);
            }
        } else {
            result.setMessage("权限未发生变化！");
        }
        return result;
    }

    /**
     * 跳转到添加页面
     * 
     * @Title toAdd
     * @author 吕凯
     * @date 2019年1月14日 上午11:43:14
     * @param request
     * @param id
     *            void
     */
    public void toAdd(HttpServletRequest request, Long id) {
        SysMenuModel parModel = getOne(request, SysMenuModel.class, id); // 获取父id
        SysMenuModel model = new SysMenuModel();
        if (parModel != null) {
            model.setParentId(parModel.getId());
        }
        /*RequestMappingHandlerMapping mapping = SpringContextHolder.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        List<String> urlList = new ArrayList<>();
        for (RequestMappingInfo info : map.keySet()) {
            // 获取url的Set集合，一个方法可能对应多个url
            Set<String> patterns = info.getPatternsCondition().getPatterns();
            for (String url : patterns) {
                urlList.add(url);
            }
        }
        request.setAttribute("urls", urlList);*/
        request.setAttribute("model", model);
    }

    /**
     * 获取菜单目录下的icon文件
     * 
     * @Title getMenuIcons
     * @author 吕凯
     * @date 2019年4月8日 下午12:19:27
     * @return List<String>
     */
    public List<String> getMenuIcons(HttpServletRequest request) {
//      File menuDir = new File(PathUtil.getClassRootPath(), "/static/images/menu/"); // 打成jar包时获取不到，需要另外处理
//      List<String> menuFiles = Arrays.asList(menuDir.list());
        List<String> menuFiles = new ArrayList<>();
        Resource[] resources = ResourceUtils.getResources("classpath*:**/images/menu/*");
        for (Resource resource : resources) {
            menuFiles.add(resource.getFilename());
        }
        if (ListUtils.isNotEmpty(menuFiles)) {
            request.setAttribute("menuIcons", menuFiles);
        }
        return menuFiles;
    }

    /**
     * 根据输入的关键字返回匹配的url
     * 
     * @Title getUrls
     * @author 吕凯
     * @date 2019年7月30日 下午4:56:34
     * @param request
     * @return List<String>
     */
    public List<String> getUrls(HttpServletRequest request) {
        return getUrls(request, null);
    }

    /**
     * 
     * 根据输入的关键字返回匹配的url
     * 
     * @Title getUrls
     * @author 吕凯
     * @date 2019年7月30日 下午5:31:45
     * @param request
     * @param maxNum
     *            显示多少条数据
     * @return List<String>
     */
    public List<String> getUrls(HttpServletRequest request, Integer maxNum) {
        if (maxNum == null) {
            maxNum = LIST_MAX_NUM;
        }
        String urlPattern = getString("name");
        if (urlPattern != null) {
            urlPattern = urlPattern.trim();
            urlPattern = SharedVarsUtil.delInnerVars(urlPattern, null); // 转换内置变量
            String projectName = Global.getProjectName();
            if (StringUtils.isNotEmpty(projectName)) { // 替换项目名为空字符
                urlPattern = urlPattern.replaceFirst(projectName, "");
            }
        }
        List<String> urlList = new ArrayList<>();
        /* RequestMappingHandlerMapping mapping = SpringContextHolder.getBean(RequestMappingHandlerMapping.class);
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        for (RequestMappingInfo info : map.keySet()) {
            // 获取url的Set集合，一个方法可能对应多个url
            Set<String> patterns = info.getPatternsCondition().getPatterns();
            HandlerMethod handlerMethod = map.get(info);
            log.warn(handlerMethod.getMethod().getDeclaringClass() + " c");
            for (String url : patterns) {
                if (StringUtils.isBlank(urlPattern) || url.contains(urlPattern)) {
                    urlList.add(url);
                }
            }
        }
        if (ListUtils.isNotEmpty(urlList)) {
            urlList.sort((a, b) -> a.length() - b.length()); // 按长度，短的在前
            urlList = urlList.stream().limit(maxNum).collect(Collectors.toList()); // 截取前10个匹配结果
            if (request != null) { // 赋值给request
                request.setAttribute("urls", urlList);
            }
        }*/
        urlList = MappingUrlCacheUtil.getUrl(urlPattern, maxNum);
        List<String> urlShowList = new ArrayList<>();
        // 内置参数转换
        urlList.stream().forEach(url -> {
            if (adminPath != null && url.startsWith(adminPath + "/")) { // 如果为空字符串也执行
                url = RegExUtils.replaceFirst(url, adminPath + "/", "\\${ctxPathA}/"); // 转为动态变量
            } else if (frontPath != null && url.startsWith(frontPath + "/")) {
                url = RegExUtils.replaceFirst(url, frontPath + "/", "\\${ctxPathF}/"); // 转为动态变量
            } else {
                url = "${ctxPath}" + url;
            }
            urlShowList.add(url); // for循环不会改变原来的值需要赋值个新对象
        });
        if (request != null) { // 赋值给request
            request.setAttribute("urls", urlShowList);
        }
        return urlShowList;
    }

    public static void main(String[] args) {
//        SysMenuService service = new SysMenuService();
//        TransactionManager.start();
//        try {
//            service.getBaseDAO().execSql("insert into sys_user_roles(id,roleId,userId) values(1,1,1) ");
//            service.getBaseDAO().execSql("insert into sys_user_roles(id,roleId,userId) values(2,1,2) ");
//            service.getBaseDAO().execSql("insert into sys_user_roles(id,roleId,userId) values(3,1,3) ");
//        } catch (Exception e) {
//            e.printStackTrace();
//        } finally {
//            try {
//                TransactionManager.commit();
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.stream().forEach(obj -> {
            obj = 3;
        });
        System.out.println(list);
    }

}
